package com.atguigu.exam.service.impl;


import com.atguigu.exam.exception.ExamException;
import com.atguigu.exam.entity.Category;
import com.atguigu.exam.entity.Question;
import com.atguigu.exam.mapper.CategoryMapper;
import com.atguigu.exam.mapper.QuestionMapper;
import com.atguigu.exam.service.CategoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Autowired
    private QuestionMapper questionMapper;

    @Override
    public List<Category> getCategoriesWithCount() {

        //添加wrapper,设置查询条件
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(Category::getSort);
        //获取所有的分类,并按照升序排序
        List<Category> categoryList = baseMapper.selectList(wrapper);//此时获取的集合不包含count字段
        //获取每个分类下的题目数量统计,查询question表根据categoryId进行分组,查找每个分组下的题目数量
        fillQuestionCount(categoryList);
        return categoryList;
    }


    @Override
    public List<Category> getCategoryTree() {
        //获取所有的分类,并按照升序排序
        List<Category> categoryList = baseMapper.selectList(new LambdaQueryWrapper<Category>().orderByAsc(Category::getSort));
        //将获取排列完的分类进行填充count
        fillQuestionCount(categoryList);
        //创建树结构
        List<Category> categoryTree = buildTree(categoryList);
        return categoryTree;
    }

    @Override
    public void saveCategory(Category category) {
        //根据父id和name进行查询
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getParentId, category.getParentId()).eq(Category::getName, category.getName());
        Category isExistCategory = baseMapper.selectOne(wrapper);
        if (isExistCategory != null) {
            //获取父id
            Long parentId = category.getParentId();
            //根据父id获取对应的category对象
            Category parentCategory = baseMapper.selectById(parentId);
            //表明该category存在,抛异常
            throw new ExamException(111, "父分类<" + parentCategory.getName() + ">下已存在<" + isExistCategory.getName() + ">分类,请重新输入分类名称");
        }
        baseMapper.insert(category);
    }

    @Override
    public void updateCategoryById(Category category) {
        //校验,在同一个父类下可以和自己的名字相同,不能和其他子分类的名字相同
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        //首先,根据parentId进行查询,保证在同一父分类下
        wrapper.eq(Category::getParentId, category.getParentId());
        //通过id确保该分类不是和自己是同一个分类
        wrapper.ne(Category::getId, category.getId());
        //根据传入的category的name进行条件查询
        wrapper.eq(Category::getName, category.getName());
        //调用baseMapper中的exists方法,查看满足上述条件是否存在
        boolean exists = baseMapper.exists(wrapper);
        if (exists) {
            //存在,表明有重复的子分类名称且不是传入的category,抛异常
            //获取当前传入分类的父分类id
            Long parentId = category.getParentId();
            //根据父id查询到父分类
            Category parentCategory = baseMapper.selectById(parentId);
            //传入名字存在,抛异常
            throw new ExamException(222, "父分类<" + parentCategory.getName() + ">下已存在<" + category.getName() + ">分类,请重新输入要修改的分类名称");
        }
        baseMapper.updateById(category);
    }

    @Override
    public void removeCategoryById(Long id) {
        //两个条件下不能删除分类
        //1.在分类下还有题目
        Long questionCount = questionMapper.selectCount(new LambdaQueryWrapper<Question>().eq(Question::getCategoryId, id));
        System.out.println("questionCount = " + questionCount);
        //2.在分类下还有子分类
        Long childrenCount = baseMapper.selectCount(new LambdaQueryWrapper<Category>().eq(Category::getParentId, id));
        System.out.println("childrenCount = " + childrenCount);
        //进行条件判断,questionCount和childrenCount都必须大于0,表示不能删除,questionCount和childrenCount等于0,表示可以删除
        if (questionCount > 0L || childrenCount > 0L) {
            //不能删除,抛异常
            throw new ExamException(333, "该分类下有子分类或者该分类下有题目，不能删除");
        }
        baseMapper.deleteById(id);
    }

    /*@Override
    public void updateCategoryById(Category category) {
        //根据父id进行查询,获取所有的子分类
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getParentId, category.getParentId());
        List<Category> childrenCategoryList = baseMapper.selectList(wrapper);
        //将子分类转换成所有子分类的名称
        List<String> childrenCategoryNames = childrenCategoryList.stream().map(Category::getName).collect(Collectors.toList());
        //将传入的category中的名字和childrenCategoryNames进行比较,看是否包含
        if (childrenCategoryNames.contains(category.getName())) {
            //如果进if表明包含传入的名字,还要再次进行判断是不是自己本身,如果是自己本身,还可以对其他数据进行修改
            //根据分类名称查找当前分类
            Category oldCategory = baseMapper.selectOne(new LambdaQueryWrapper<Category>().eq(Category::getName, category.getName()));
            //进行判断,查看是不是当前分类本身
            if (oldCategory.getId().equals(category.getId())) {
                baseMapper.updateById(category);
            } else {
                //获取当前传入分类的父分类id
                Long parentId = category.getParentId();
                //根据父id查询到父分类
                Category parentCategory = baseMapper.selectById(parentId);
                //传入名字存在,抛异常
                throw new ExamException(222, "父分类<" + parentCategory.getName() + ">下已存在<" + category.getName() + ">分类,请重新输入要修改的分类名称");
            }
        }
        baseMapper.updateById(category);
    }*/

    //生成树结构
    private List<Category> buildTree(List<Category> categoryList) {
        //将传递过来的集合按照parentId进行分组,生成Map
        Map<Long, List<Category>> parentIdMap = categoryList.stream().collect(Collectors.groupingBy(Category::getParentId));
        //遍历categoryList
        categoryList.forEach(category -> {
            //获取当前分类的id
            Long id = category.getId();
            //根据当前id获取子类列表
            List<Category> childrenCategories = parentIdMap.getOrDefault(id, new ArrayList<Category>());
            //将子类列表添加到category的children中
            category.setChildren(childrenCategories);
            //将子类列表中的count转换成Long,并进行加和
            long childrenCountSum = childrenCategories.stream().mapToLong(c -> c.getCount() != null ? c.getCount() : 0L).sum();
            //获取当前分类下的count数
            Long parentCount = category.getCount();
            //将父分类和子分类的count相加
            category.setCount(parentCount + childrenCountSum);
        });
        //过滤parentId为0的category分类
        List<Category> categoryTree = categoryList.stream().filter(category -> category.getParentId() == 0).collect(Collectors.toList());
        return categoryTree;
    }

    //为category集合填充question数量
    private void fillQuestionCount(List<Category> categoryList) {
        List<Map<Long, Long>> countList = questionMapper.getCategoryCount();
        //将countList 转换成 Map
        Map<Long, Long> countMap = countList.stream().collect(Collectors.toMap(m -> m.get("category_id"), m -> m.get("count")));
        //遍历categoryList将category中的count属性赋值
        categoryList.forEach(category -> {
            //从countMap中获取count
            Long questionCount = countMap.getOrDefault(category.getId(), 0L);
            //为categoryList中的count赋值
            category.setCount(questionCount);
        });
    }
}